Skip to content

[None][feat] Add DeepSeek DSpark speculative decoding#15808

Merged
longlee0622 merged 6 commits into
NVIDIA:mainfrom
longlee0622:dev/dspark-spec-dec-pr
Jul 18, 2026
Merged

[None][feat] Add DeepSeek DSpark speculative decoding#15808
longlee0622 merged 6 commits into
NVIDIA:mainfrom
longlee0622:dev/dspark-spec-dec-pr

Conversation

@longlee0622

@longlee0622 longlee0622 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds DeepSeek DSpark speculative decoding (the DeepSeek-V4-Pro-DSpark draft) to the PyTorch backend.

DSpark extends the MTP one-model family with three full DeepSeek-V4 draft blocks under the mtp.* namespace. One backbone forward proposes a block of tokens, a lightweight sequential Markov head refines the proposal, and a per-position confidence head can truncate it. Acceptance still uses standard target verification, so greedy correctness is preserved independently of draft quality.

The implementation runs end-to-end on 8×B300 as a one-engine drafter, and the generation draft path can be captured into the target CUDA graph.

What is added

  • Draft model: DSparkBlock, DSparkDraftModel, and DSparkForCausalLM, including mtp.{stage}.* to mtp_layers.{stage}.* weight remapping and FP8 UE8M0 / MXFP4 expert loading.
  • Draft components: Markov/confidence heads, draft input/output handling, and scalar plus batched captured-context attention.
  • Runtime integration: DSpark worker and metadata, SpeculativeDecodingMode.DSPARK, DSparkDecodingConfig, one-engine wiring, and DSpark-gated target hidden-state capture.
  • Tests: hardware-agnostic unit coverage, CUDA-graph capture/replay coverage, 8-GPU end-to-end coverage, and a full GSM8K LLM API accuracy gate.

CUDA-graph safety

The default generation draft path is batched and avoids host synchronization and data-dependent shapes. It uses per-request start-position tensors, RoPE gathered from a fixed table, slot-indexed rolling windows, and fixed-width masked top-k. The batched path is numerically checked against the scalar reference path.

No DSpark-specific CUDA-graph flag is required.

Validated LLM API configuration

The new full-accuracy LLM API test uses the following topology and backend:

from tensorrt_llm import LLM
from tensorrt_llm.llmapi import (
    DSparkDecodingConfig,
    KvCacheConfig,
    MoeConfig,
)

model_path = "/path/to/DeepSeek-V4-Pro-DSpark"

llm = LLM(
    model_path,
    attn_backend="TRTLLM",
    tensor_parallel_size=8,
    moe_expert_parallel_size=8,
    enable_attention_dp=True,
    moe_config=MoeConfig(backend="MEGAMOE_DEEPGEMM"),
    max_seq_len=4096,
    max_num_tokens=4096,
    kv_cache_config=KvCacheConfig(
        enable_block_reuse=False,
        free_gpu_memory_fraction=0.5,
    ),
    enable_chunked_prefill=False,
    disable_overlap_scheduler=True,
    custom_tokenizer="deepseek_v4",
    speculative_config=DSparkDecodingConfig(
        max_draft_len=5,
        speculative_model=model_path,
    ),
)

The draft inherits the target MoE backend. The validated high-acceptance path is DEP8 + MegaMoE DeepGEMM. CUTLASS remains a compatible fallback; TRTLLM-Gen blockScaleMoe cannot route this checkpoint's 384-expert / 8-group layout.

Correctness and accuracy

  • Hardware-agnostic unit tests: heads, draft I/O, weight schema, attention, batched-versus-scalar equivalence, worker, and metadata.
  • Numerical faithfulness: DeepSpec-reference attention cosine similarity is approximately 0.999994, with full-chain and live-capture goldens.
  • 8-GPU end-to-end test: eager and CUDA-graph modes generate coherent greedy output and assert a positive accepted-draft count.
  • Full GSM8K LLM API test: test_gsm8k_dep8_megamoe_deepgemm runs all 1,319 samples with TP8, EP8, attention DP, and MegaMoE DeepGEMM. The measured score is 96.475%; the committed reference floor is 96.0% to allow normal run-to-run variation.

The 8-GPU MoE path is not bit-reproducible across independent runs because of non-associative FP atomics, so the end-to-end test does not require token-for-token equality with a separate no-spec run. The verification invariant is covered by unit tests and numerical goldens.

Acceptance length: DL1-DL7 sweep

Measured offline on 8×B300 with the same TP8 + EP8 + attention DP + MegaMoE DeepGEMM configuration as the LLM API test. The sweep used greedy decoding, 12 prompts per dataset / thinking mode / draft length, up to 512 new tokens, with chunked prefill and CUDA graph disabled.

AL is avg_decoded_tokens_per_iter: committed tokens per target step, including the one guaranteed target token. DL is max_draft_len, so AL is in [1, DL+1]. Each dataset cell below is Thinking-OFF / Thinking-ON.

DL GSM8K HumanEval MATH500 Six-regime average
1 1.877 / 1.908 1.896 / 1.911 1.909 / 1.927 1.905
2 2.653 / 2.704 2.672 / 2.669 2.698 / 2.703 2.683
3 3.200 / 3.411 3.285 / 3.370 3.231 / 3.448 3.324
4 3.914 / 3.905 3.769 / 3.826 4.001 / 4.054 3.912
5 4.142 / 4.208 4.008 / 4.244 4.315 / 4.520 4.240
6 4.286 / 4.875 4.350 / 4.648 4.800 / 4.764 4.621
7 4.687 / 4.958 4.264 / 4.401 4.682 / 4.809 4.634

Key observations:

  • The aggregate AL rises monotonically from 1.905 at DL1 to 4.634 at DL7.
  • DL6 and DL7 are effectively a plateau in this N=12 sample: DL7 improves the six-regime average by only 0.013.
  • Best GSM8K AL is at DL7 (4.687 / 4.958); HumanEval peaks at DL6 (4.350 / 4.648); MATH500 peaks at DL6 for Thinking-OFF (4.800) and DL7 for Thinking-ON (4.809).
  • Against a matched CUTLASS / no-attention-DP baseline using the same harness, source, wheel, node, and prompts, the combined configuration improves average AL by 10.3%, 22.6%, 36.8%, 51.5%, 64.4%, 86.1%, and 104.1% for DL1 through DL7.
  • Because both attention DP and the MoE backend changed together, the result establishes the benefit of the combined production configuration but does not attribute the gain to either knob independently.
  • This sweep measures acceptance length, not throughput. It is not sufficient on its own to change the default draft length.

All 42 reported AL values were validated against the raw log, all seven draft-length runs exited successfully, and the sweep completed successfully.

Notes and limitations

  • Acceptance remains workload- and thinking-mode-dependent; max_draft_len should be tuned together with end-to-end throughput for the intended workload.
  • Confidence-based dynamic drafting is not enabled in this PR.

PR checklist

  • The description explains the implementation, validated configuration, accuracy gate, and acceptance results.
  • Unit, CUDA-graph, 8-GPU end-to-end, and full GSM8K LLM API tests cover the new paths.
  • The change follows the TensorRT-LLM coding and contribution guidelines to the best of the author's knowledge.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new DSpark speculative decoding mode across the TensorRT-LLM _torch stack: pure-torch captured-context attention kernels, Markov/confidence draft heads, a staged draft model with checkpoint remapping, a worker managing rolling KV windows, target-model capture hooks, and LLM API config/validation, plus extensive unit and e2e tests. Unrelated fixes tighten DeepSeek-V4 config validation and an mHC head reshape.

Changes

DSpark Speculative Decoding

Layer / File(s) Summary
Speculative mode dispatch
tensorrt_llm/_torch/speculative/interface.py, tensorrt_llm/_torch/speculative/utils.py, tensorrt_llm/_torch/models/modeling_speculative.py
Adds DSPARK enum member and is_dspark(), wires get_spec_metadata/get_spec_worker/get_draft_model/load_draft_weights to dispatch to DSpark implementations.
Captured-context attention kernels
tensorrt_llm/_torch/speculative/dspark_attention.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_attention.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_cuda_graph.py
Adds RoPE, top-k index selection, sparse attention with sink, and scalar/batched forward attention functions, with CPU correctness and CUDA-graph capture/replay tests.
Draft heads and proposal
tensorrt_llm/_torch/speculative/dspark_heads.py, tensorrt_llm/_torch/speculative/dspark_draft.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_heads.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_draft.py
Adds Markov-bias heads (vanilla/gated/RNN), confidence head, capture projection, and dspark_propose full-block token proposal with confidence-based truncation, with unit tests.
Staged draft model and checkpoint loading
tensorrt_llm/_torch/models/modeling_dspark.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_weight_schema.py
Adds checkpoint key remapping, DSparkBlock, DSparkDraftModel (forward/forward_batched/context windows), DSparkForCausalLM weight-loading wrapper, and weight-schema consistency tests.
Worker and rolling KV windows
tensorrt_llm/_torch/speculative/dspark.py, tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py
Adds DSparkSpecMetadata capture hooks and DSparkWorker slot/window management with eager and batched draft generation plus acceptance/forward orchestration.
Target model capture and mHC head fix
tensorrt_llm/_torch/models/modeling_deepseekv4.py, tensorrt_llm/_torch/modules/mhc/hyper_connection.py
Extends decoder layer forward/forward_MoE to support DSpark hidden-state capture; fixes HCHead.forward to preserve leading dimensions across reshape.
LLM API config and DeepSeek-V4 guards
tensorrt_llm/llmapi/llm_args.py, tensorrt_llm/llmapi/__init__.py, tensorrt_llm/_torch/model_config.py, tests/unittest/_torch/test_model_config.py, tests/unittest/api_stability/references_committed/llm.yaml
Adds DSparkDecodingConfig and backend validation, tightens num_nextn_predict_layers/compress_ratios handling for DeepSeek-V4 with a fail-fast error and regression test.
End-to-end test
tests/unittest/_torch/speculative/hw_agnostic/test_dspark.py
Adds an 8-GPU e2e pytest generating text with DSpark decoding and validating non-degenerate acceptance rate.

Sequence Diagram(s)

sequenceDiagram
  participant TargetModel as DeepseekV4DecoderLayer
  participant SpecMetadata as DSparkSpecMetadata
  participant DSparkWorker
  participant DraftModel as DSparkDraftModel

  TargetModel->>SpecMetadata: maybe_capture_hidden_states(resolved_residual)
  DSparkWorker->>SpecMetadata: prepare(request_ids)
  DSparkWorker->>SpecMetadata: get_hidden_states()
  DSparkWorker->>DSparkWorker: write_context_windows / back-fill accepted tokens
  DSparkWorker->>DraftModel: forward_batched(main_hidden, bonus_token_ids, kv_windows, slots)
  DraftModel->>DraftModel: _forward_stage (attention + MoE) per stage
  DraftModel->>DraftModel: forward_head (dspark_propose)
  DraftModel-->>DSparkWorker: draft tokens, num_proposed
  DSparkWorker-->>TargetModel: next_draft_tokens
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • NVIDIA/TensorRT-LLM#12794: Extends the same SpeculativeDecodingMode/is_parallel_draft interface and get_draft_model dispatch to add a new draft mode (DFlash), mirroring the DSpark integration points in this PR.

Suggested reviewers

  • arysef
  • nv-guomingz
  • jieli-matrix
  • 2ez4bz
  • JunyiXu-nv
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding DeepSeek DSpark speculative decoding.
Description check ✅ Passed The description is detailed and largely matches the template, covering summary, validation, tests, and checklist items.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py (1)

151-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Coverage is insufficient for confidence-based truncation in the worker.

These tests only cover slot/window bookkeeping. They never stub draft_model.forward() / forward_batched() to return num_proposed < block_size, so the worker contract that should honor DSpark truncation is still untested. Please add that regression in tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py (and, if you want end-to-end coverage, follow up in tests/unittest/_torch/speculative/hw_agnostic/test_dspark.py).

As per path instructions, coverage here is insufficient and the feedback should name the target test files explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py` around
lines 151 - 210, The current tests only verify slot/window bookkeeping and do
not cover the confidence-based truncation path in the worker. Add a regression
test in test_dspark_worker that stubs draft_model.forward() or forward_batched()
to return num_proposed less than block_size, then assert the worker honors
DSpark truncation behavior; use _lazy_init, prepare, and the draft model call
path to locate the right spot. If you want broader coverage, add a matching
end-to-end test in test_dspark as well.

Source: Path instructions

tests/unittest/_torch/test_model_config.py (1)

173-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

DSpark config coverage is still missing.

This regression closes the compress_ratios=None gap, but none of the new DSpark validation in tensorrt_llm/llmapi/llm_args.py is covered here. Please add focused cases in tests/unittest/_torch/test_model_config.py or a new tests/unittest/llmapi/test_llm_args.py for same-checkpoint speculative_model handling and rejecting block_size != max_draft_len, so the first signal is not the 8-GPU e2e.

As per path instructions, "tests/**: Act as a QA engineer reviewing test changes and coverage for TensorRT-LLM. Keep feedback actionable: suggest concrete list file names and whether coverage is sufficient, insufficient, or needs follow-up outside the PR."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/test_model_config.py` around lines 173 - 198, Coverage
is insufficient for the new DSpark validation in llm_args.py. Add focused tests
in tests/unittest/_torch/test_model_config.py or a new
tests/unittest/llmapi/test_llm_args.py that exercise the speculative_model
same-checkpoint path and verify block_size is rejected when it differs from
max_draft_len. Use the relevant entry points ModelConfig.from_pretrained and the
llm_args validation logic so the failure is caught in unit tests instead of only
in e2e.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/models/modeling_dspark.py`:
- Around line 367-377: The DSpark confidence path is always enabling
`with_markov` even when `build_markov_head()` returns `None`, which later makes
`DSparkConfidenceHead.forward()` assert on missing `prev_embeddings`. Update the
initialization in `DSparkModel` so `with_markov` is derived from whether
`self.markov_head` actually exists (or from `self.markov_rank > 0`), and pass
that value into `DSparkConfidenceHead` instead of hardcoding `True`. This should
keep `dspark_propose()` and `DSparkConfidenceHead` aligned when
`dspark_markov_rank=0`.

In `@tensorrt_llm/_torch/speculative/dspark.py`:
- Around line 339-347: `num_proposed` is being computed by
`draft_model.forward*()` but then discarded, so speculative scheduling still
always queues a full `block_size` block. Update the DSpark flow in `dspark.py`
to capture the second return value from both draft paths and thread it through
`next_draft_tokens` / the verifier so the scheduled draft length is truncated
according to `confidence_threshold`. Use the existing `draft_model.forward*()`,
`next_draft_tokens`, and speculative verification logic to ensure the count
affects runtime behavior, then add a regression test covering truncated draft
blocks.

In `@tensorrt_llm/llmapi/llm_args.py`:
- Around line 5137-5179: Move the DSpark validation into this
`DSparkDecodingConfig` handling block in `llm_args.py` so misconfigurations fail
early: explicitly reject `speculative_model=None` when `speculative_config` is
`DSparkDecodingConfig`, and validate that the resolved `block_size` matches
`max_draft_len` after loading any draft config overrides. Keep the checks close
to the existing `spec_cfg` resolution logic and use the `DSparkDecodingConfig` /
`speculative_model` / `max_draft_len` symbols so the invariant is enforced
before downstream DSpark model construction.
- Around line 2479-2484: The confidence_threshold field in llm_args.py is
currently unconstrained, so it can accept values outside the valid probability
range and cause DSpark truncation misconfiguration. Update the
confidence_threshold definition in the relevant args/model to enforce a [0, 1]
bound using Pydantic field constraints, and keep the existing default and
description intact. Use the confidence_threshold symbol to locate the field and
ensure the validation is declarative rather than handled by a custom validator.

In `@tests/unittest/_torch/speculative/hw_agnostic/test_dspark_cuda_graph.py`:
- Around line 214-252: The CUDA graph test only captures the non-persistent
branch, so it misses the production write-through path in
dspark_attention_forward_batched. Update
test_batched_attention_cuda_graph_capture_replay to also exercise persist=True
with a separate cache buffer, using the same CUDA graph capture/replay pattern.
Add an assertion that verifies the expected rolling KV window mutation after
replay, alongside the existing output comparison.

In `@tests/unittest/_torch/speculative/hw_agnostic/test_dspark.py`:
- Around line 107-114: Wrap the DSpark speculative decoding section in a
try/finally so the 8-GPU LLM created in spec_llm is always shut down even if
generate() or the output extraction for
spec_out/spec_texts/spec_ids/avg_accepted fails. Keep the existing spec_config,
spec_llm.generate, and shutdown logic, but move spec_llm.shutdown() into the
finally block to prevent leaked model/process-group state.

---

Nitpick comments:
In `@tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py`:
- Around line 151-210: The current tests only verify slot/window bookkeeping and
do not cover the confidence-based truncation path in the worker. Add a
regression test in test_dspark_worker that stubs draft_model.forward() or
forward_batched() to return num_proposed less than block_size, then assert the
worker honors DSpark truncation behavior; use _lazy_init, prepare, and the draft
model call path to locate the right spot. If you want broader coverage, add a
matching end-to-end test in test_dspark as well.

In `@tests/unittest/_torch/test_model_config.py`:
- Around line 173-198: Coverage is insufficient for the new DSpark validation in
llm_args.py. Add focused tests in tests/unittest/_torch/test_model_config.py or
a new tests/unittest/llmapi/test_llm_args.py that exercise the speculative_model
same-checkpoint path and verify block_size is rejected when it differs from
max_draft_len. Use the relevant entry points ModelConfig.from_pretrained and the
llm_args validation logic so the failure is caught in unit tests instead of only
in e2e.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fec2a059-f520-48da-ac10-e69c8dd54c96

📥 Commits

Reviewing files that changed from the base of the PR and between 9a26938 and 533cd80.

📒 Files selected for processing (22)
  • tensorrt_llm/_torch/model_config.py
  • tensorrt_llm/_torch/models/modeling_deepseekv4.py
  • tensorrt_llm/_torch/models/modeling_dspark.py
  • tensorrt_llm/_torch/models/modeling_speculative.py
  • tensorrt_llm/_torch/modules/mhc/hyper_connection.py
  • tensorrt_llm/_torch/speculative/dspark.py
  • tensorrt_llm/_torch/speculative/dspark_attention.py
  • tensorrt_llm/_torch/speculative/dspark_draft.py
  • tensorrt_llm/_torch/speculative/dspark_heads.py
  • tensorrt_llm/_torch/speculative/interface.py
  • tensorrt_llm/_torch/speculative/utils.py
  • tensorrt_llm/llmapi/__init__.py
  • tensorrt_llm/llmapi/llm_args.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_attention.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_cuda_graph.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_draft.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_heads.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_weight_schema.py
  • tests/unittest/_torch/speculative/hw_agnostic/test_dspark_worker.py
  • tests/unittest/_torch/test_model_config.py
  • tests/unittest/api_stability/references_committed/llm.yaml

Comment thread tensorrt_llm/_torch/models/modeling_dspark.py
Comment thread tensorrt_llm/_torch/speculative/dspark.py Outdated
Comment thread tensorrt_llm/llmapi/llm_args.py Outdated
Comment thread tensorrt_llm/llmapi/llm_args.py
Comment thread tests/unittest/_torch/speculative/hw_agnostic/test_dspark.py Outdated
@longlee0622
longlee0622 requested a review from a team as a code owner July 2, 2026 08:53
@longlee0622
longlee0622 force-pushed the dev/dspark-spec-dec-pr branch 3 times, most recently from 5e177ce to c8fcd3d Compare July 3, 2026 05:07
@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57370 [ run ] triggered by Bot. Commit: 15169d5 Link to invocation

@longlee0622 longlee0622 added the api-compatible Accepted LLM API contract change that is backwards-compatible label Jul 3, 2026
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57370 [ run ] completed with state FAILURE. Commit: 15169d5
/LLM/main/L0_MergeRequest_PR pipeline #46121 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57435 [ run ] triggered by Bot. Commit: 15169d5 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57435 [ run ] completed with state SUCCESS. Commit: 15169d5
/LLM/main/L0_MergeRequest_PR pipeline #46174 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@longlee0622
longlee0622 force-pushed the dev/dspark-spec-dec-pr branch from 15169d5 to fa6461a Compare July 3, 2026 18:22
@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57501 [ run ] triggered by Bot. Commit: fa6461a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #57501 [ run ] completed with state ABORTED. Commit: fa6461a

Link to invocation

@longlee0622
longlee0622 force-pushed the dev/dspark-spec-dec-pr branch from 28e16ea to c0c2ab0 Compare July 17, 2026 07:52
Comment thread tensorrt_llm/_torch/speculative/dspark.py Outdated
@longlee0622
longlee0622 force-pushed the dev/dspark-spec-dec-pr branch from 623e086 to c0b95fe Compare July 17, 2026 09:28

@pengbowang-nv pengbowang-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve for attention part

@WeiHaocheng

Copy link
Copy Markdown
Collaborator

LGTM in models part.

@BowenFu BowenFu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Reviewed for regressions to existing/default (non-DSpark) behavior: all shared-path changes are either DSpark-gated (is_dspark()) or provably behavior-preserving — the modeling_deepseekv4.py deletions are a verbatim closure→helper refactor, the widened allgather payloads unpack consistently, and the mla/hyper_connection changes are no-ops for existing inputs. API additions are purely additive with the manifest updated. Non-DSpark paths unaffected.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
Make the checkpoint's dspark_target_layer_ids authoritative for DSpark
speculative decoding. When target_layer_ids is unset it is copied from
the checkpoint verbatim (order preserved, since main_proj columns are
order-dependent). An explicit override that does not exactly match the
checkpoint list is now rejected during config validation instead of
failing later with a projection shape mismatch (different count) or
silently degrading acceptance (same count, different/reordered layers).

Add unit coverage for defaulting, matching override, mismatched count,
same-count-different-layers, and order-mismatch cases.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
Rebase DSpark onto the unified one-model speculative-decoding base introduced
by PR NVIDIA#15775 and route production and acceptance through the shared entry
points instead of hand-rolling them in DSparkWorker:

- Produce draft tokens via SpecWorkerBase.sample_draft_tokens on the per-position
  corrected block logits [num_gens, K, vocab] (surfaced from the draft model via
  the existing return_logits path), letting the base do greedy/rejection sampling,
  TP gather, d2t, and the draft_probs scatter.
- Accept via SpecWorkerBase.sample_and_accept_draft_tokens (strict or rejection),
  dropping the local _sample_and_accept_draft_tokens_base call.
- Fill context requests draft-prob rows with a one-hot via
  write_context_onehot_draft_probs.
- Register DSpark in the rejection gate (is_supported / is_new_rejection_method)
  and thread vocab_size / draft_vocab_size / use_rejection_sampling into
  DSparkSpecMetadata so the slot-indexed rejection buffers are allocated.

Greedy behavior is preserved (the base argmaxes the same corrected logits the
head produced). Adds a mixed-batch (context + gen) worker orchestration test.

Validated: 60/60 hw_agnostic unit tests; 8xB300 e2e (BENCH_OK); and the full
DL1-7 thinking on/off DEP8+MegaMoE-DeepGEMM AL sweep matches the previously
collected baseline within N=12 nondeterministic variance.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
The optional real-fp8-MLA draft-attention path (env TLLM_DSPARK_REAL_MLA /
DSparkDraftModel.use_real_mla) was opt-in, never used by any production or
benchmark config (all use the default bf16 captured-context path), and is
currently broken: it runs torch.einsum/baddbmm on Float8_e4m3fn tensors, which
torch does not implement ("baddbmm_cuda not implemented for Float8_e4m3fn").
It is not on the roadmap, so remove it rather than ship dead/broken code.

Removed:
- _dspark_mla_attention() and the TLLM_DSPARK_REAL_MLA env / use_real_mla attr
  and all use_real_mla branches in modeling_dspark.py (attention dispatch,
  weight-load setup, and the forward_batched NotImplementedError guard).
- The eager per-request DSparkWorker._draft_gen_block fallback (which existed
  only for real-fp8-MLA) and the _use_batched toggle; the worker is now always
  the batched, CUDA-graph-safe path.
- The obsolete legacy-real-mla worker test.

The default bf16 batched path is unchanged (byte-identical, just un-nested).
Validated: 59/59 DSpark hw_agnostic unit tests pass (worker/draft/heads/
attention/cuda_graph). Net -256 lines.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
… width

Address PR review (r3601639329). DSparkWorker.forward passed
gen_logits.shape[-1] to write_context_onehot_draft_probs, but DSpark surfaces
vocab-sharded draft logits (unlike DFlash, which gathers in the worker), so
under tensor parallelism that is the pre-gather shard width.
sample_draft_tokens all-gathers the logits to full vocab and scatters
draft_probs at that full width (publishing draft_probs_last_dim), so writing the
context requests' one-hot at the shard width leaves the trailing columns stale
and corrupts rejection acceptance on context-to-gen transitions.

Use spec_metadata.draft_probs_last_dim (the width the gen scatter just
published) for the context one-hot. Update the mixed-batch worker test to assert
the one-hot uses the scatter width, not the sharded gen_logits width.

Only affects the rejection-sampling path under plain TP (no-op for greedy and
gated off under attention-DP); validated by the DSpark hw_agnostic unit suite
(59 passed).

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
…onfig

Confidence-based dynamic drafting is intentionally not enabled in this PR (the
draft path always calls with confidence_threshold=0.0). Keep the confidence head
as scaffolding for a follow-up, but address the related review feedback and
remove the user-facing knobs that are not wired up yet:

- Gate DSparkConfidenceHead(with_markov=...) on markov_rank > 0 (was hardcoded
  True). build_markov_head() returns None for markov_rank <= 0, and
  dspark_propose then passes no prev_embeddings, which would trip the
  prev_embeddings assert in DSparkConfidenceHead.forward (review r3502819934).
- Remove the unwired DSparkDecodingConfig fields enable_confidence_head and
  confidence_threshold (read nowhere at runtime; review r3547358128). They will
  be re-added when the confidence head is actually wired into the speculative
  scheduler/verifier. Regenerate the LLM args golden manifest accordingly.
- Document in dspark_propose that num_proposed is not yet consumed and the
  confidence branch is inert scaffolding (review r3502819941).

The confidence head module and its internal plumbing remain in place. No runtime
behavior change (the confidence path was already never exercised).
Validated: DSpark hw_agnostic unit suite (24 passed) and test_llm_args DSpark
tests (9 passed).

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
@longlee0622
longlee0622 force-pushed the dev/dspark-spec-dec-pr branch from f4596f2 to e676f36 Compare July 17, 2026 10:15
@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59961 [ run ] triggered by Bot. Commit: e676f36 Link to invocation

@juney-nvidia juney-nvidia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved from API and telemetry perspectives.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59961 [ run ] completed with state FAILURE. Commit: e676f36
/LLM/main/L0_MergeRequest_PR pipeline #48355 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@longlee0622
longlee0622 enabled auto-merge (squash) July 17, 2026 13:34
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59986 [ run ] triggered by Bot. Commit: e676f36 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #59986 [ run ] completed with state FAILURE. Commit: e676f36
/LLM/main/L0_MergeRequest_PR pipeline #48380 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@longlee0622

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60059 [ run ] triggered by Bot. Commit: e676f36 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60059 [ run ] completed with state SUCCESS. Commit: e676f36
/LLM/main/L0_MergeRequest_PR pipeline #48447 completed with status: 'SUCCESS'

CI Report

Link to invocation

@longlee0622
longlee0622 merged commit 1474048 into NVIDIA:main Jul 18, 2026
8 checks passed
@longlee0622
longlee0622 deleted the dev/dspark-spec-dec-pr branch July 18, 2026 00:29
longlee0622 added a commit to longlee0622/TensorRT-LLM that referenced this pull request Jul 18, 2026
Consolidate the DSpark dev-branch documentation into a single commit and update
it to the post-merge reality of PR NVIDIA#15808:

- DSPARK_DEV.md: note the PR is merged; describe the confidence head as loaded
  scaffolding (truncation not wired); drop the removed real-fp8-MLA
  (TLLM_DSPARK_REAL_MLA) path from the design and acceptance sections.
- DSPARK_REVIEW.md: prune the items resolved in / after the merge (target-layer
  validation, gating corrected logits on return_logits, with_markov/markov_rank
  head consistency, real-fp8-MLA removal, and removal of the unwired
  enable_confidence_head / confidence_threshold config fields); reword the
  confidence-truncation and duplicate-weight items for the current code.

These notes live on the development branch only and are not part of any PR.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
longlee0622 added a commit to longlee0622/TensorRT-LLM that referenced this pull request Jul 18, 2026
Consolidate the DSpark dev-branch documentation into a single commit and update
it to the post-merge reality of PR NVIDIA#15808:

- DSPARK_DEV.md: note the PR is merged; describe the confidence head as loaded
  scaffolding (truncation not wired); drop the removed real-fp8-MLA
  (TLLM_DSPARK_REAL_MLA) path from the design and acceptance sections.
- DSPARK_REVIEW.md: prune the items resolved in / after the merge (target-layer
  validation, gating corrected logits on return_logits, with_markov/markov_rank
  head consistency, real-fp8-MLA removal, and removal of the unwired
  enable_confidence_head / confidence_threshold config fields); reword the
  confidence-truncation and duplicate-weight items for the current code.

These notes live on the development branch only and are not part of any PR.

Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-compatible Accepted LLM API contract change that is backwards-compatible

Projects

None yet

Development

Successfully merging this pull request may close these issues.